Шаг 6. Сжимаем коммиты c помощью опции squash

Бывает так: вы создали отдельную ветку и долго в ней работаете. Сделали в этой ветке много коммитов, и, возможно, не все из них хорошие.

Или так: вы отправили запрос на слияние, но руководитель проекта нашёл ошибки. Вы их исправили и каждую ошибку закоммитили отдельно, чтобы проверяющий мог быстрее разобраться в ваших исправлениях.

Эти мелкие коммиты актуальны только на момент работы или проверки, а после их нужно объединить в один. Если вы выполните обычное слияние, через fast-forward или no-fast-forward, коммиты всё равно перенесутся во вливаемую ветку, а нам бы этого не хотелось. На этот случай есть решение — опция --squash. Она позволяет сжать коммиты и создать из них один.

Давайте посмотрим, как работает squash.

Для начала убедитесь, что вы находитесь в ветке develop. Если нет, переключитесь на неё — git switch develop.

Чтобы понять смысл сквоша, сделаем два изменения и закоммитим каждое по отдельности. Для этого перейдём в index.html. Сначала сделаем первое изменение — исправим отступы для элемента <head> и <body>.

Красная стрелка указывает на добавленный отступ
Красная стрелка указывает на добавленный отступ

Добавляем изменение в индекс — git add -A.

Введена команда git add -A
Введена команда git add -A

После этого сделаем фиксацию изменения — git commit --message "feat: added indents for nested html tag elements in index.html".

Введена команда git commit --message
Введена команда git commit --message

Внесём второе изменение. Поменяем местами атрибуты у элемента <link>.

Красная стрелка указывает на атрибуты, которые были поменяны местами
Красная стрелка указывает на атрибуты, которые были поменяны местами

Снова добавим изменение в индекс — git add --all, а затем выполним фиксацию — git commit --message "feat: the attributes of the link element have been swapped".

Введена команда git commit --message
Введена команда git commit --message

После этого переключаемся на ветку main с помощью команды git switch main.

Введена команда git switch main
Введена команда git switch main

Как вы можете заметить, изменения тоже исчезли. Теперь можно приступать к сжатию коммитов с помощью опции --squash. Для этого пропишем команду git merge develop --squash.

Введена команда git merge develop --squash
Введена команда git merge develop --squash

Изменения перенеслись.

У вас мог появиться вопрос, что произошло и в чём разница? При использовании опции --squash переносятся лишь сделанные изменения, и они сразу добавляются в индекс, чтобы мы смогли самостоятельно создать коммит.

Что ещё важно знать:

  1. Слияние всегда будет происходить с использованием режима fast-forward. Если дополнительно к опции --squash написать --no-ff для использования режима no-fast-forward, она будет проигнорирована. Точно так же будет проигнорирована опция --message или -m для написания текста коммита слияния, потому что коммит мы будем создавать сами.
  2. Коммиты не переносятся — переносятся только сделанные изменения. Поэтому может возникнуть проблема с удалением ветки через опцию --delete, в нашем случае ветки develop. Дело в том, что коммиты не были перенесены, и Git до сих пор думает, что слияние не произошло. Чтобы удалить ветку, понадобится опция --force, которая сделает это принудительно.
  3. Так как коммиты не перенесены, указатель HEAD не будет обновлён. Он продолжит указывать на последний сделанный коммит в ветке main. Лишь когда мы сделаем коммит из перенесённых изменений — только тогда указатель переместится, ведь этот коммит будет считаться последним.

Это всё, что важно знать про опцию. Теперь закоммитим изменения с помощью команды git commit --message "feat: tabulation has been added, and the attributes of the link element have been swapped".

Введена команда git commit --message
Введена команда git commit --message

На самом деле это пример не лучшего коммита, так он объединяет несколько разных изменений. Мы сделали так, чтобы показать работу squash. Но при работе над реальными проектами помните: коммиты не должны описывать разные изменения.

Теперь отправим изменение в удалённый репозиторий с помощью команды git push.

Введена команда git push
Введена команда git push

Далее удалим ветку develop: она нам пока что не понадобится, в следующих демонстрациях мы создадим другую. Для удаления воспользуемся командой git branch -D develop.

Введена команда git branch -D develop
Введена команда git branch -D develop

Мы удалили ветку лишь локально — теперь её нужно убрать из удалённого репозитория. Для этого воспользуемся командой git push --delete origin develop.

Введена команда git push --delete origin develop
Введена команда git push --delete origin develop

Если вам понадобятся коммиты из ветки develop, можно будет сделать обычное слияние.

В одной из будущих демонстраций мы разберём более удобный способ сжатия коммитов. Сейчас мы перемещали изменения на другую ветку, а в другом примере мы будем работать на той же ветке. Потом этот коммит можно будет влить в другую ветку.